26. 长三角跨境电商销售分析(国际平台样例对照)

本章概要

  • 学习材料:平台折扣订单示例数据与焦点科技2018—2025真实财报两层依据。
  • 本章任务:先核对折扣组 quantity/sales/profit,再用 revenue/sell_exp/net_profit 计算销售费用率和净利率双最低要求。
  • 完成后你将得到:平台折扣守恒表、焦点科技双比率状态和壹网壹创拓展应用表。
  • 自我检查:核对按产品和日期汇总后的利润总额是否与原表一致,并确认财报期间和比较标准;若分母为零或同一报告期有多个版本,应先处理后再计算。
  • 拓展练习:将真实财报分析应用到浙江壹网壹创且不混写两层依据。

学习说明:本章只计“平台折扣方法+中国企业财务约束代理”成果;企业季度财报没有订单级折扣、成交价和商品日暴露,不计真实电商订单完成案例。

本章概览:电商数据的多维度分析

电商平台的核心数据分析问题:

  • 折扣策略:多大折扣最优?
  • 利润分析:折扣与利润的关系是什么?
  • 品类表现:哪些品类利润高?
  • 定价策略:如何平衡销量与利润?

中国主案例:南京跨境电商的预算约束

要素 课堂口径
本地资产 stock/financial_statement.h5stock/stock_basic_data.h5
对象与期间 南京焦点科技 002315.SZ,2018–2025 年季度数据
字段 地区/行业、营业收入、销售费用、净利润
决策 折扣方案不得突破销售费用率与净利率双重阈值

中国主案例:依据边界

平台订单样例用于学习折扣—利润分析;真实公司财报只检查预算约束。缺少订单级成交价与优惠字段时,不得声称识别了因果性的“最优折扣”。

分析思路与数据说明

数据来源:某国际电商平台(Superstore)销售数据

分析框架

  • 读取并清洗电商销售数据
  • 探究同一天的折扣策略差异
  • 分析不同品类的折扣情况
  • 研究折扣与利润的总体关系
  • 可视化折扣与业务指标

数据准备:导入库与读取数据

Listing 1: 电商平台数据预处理
# 注:superstore.xlsx 数据文件本地没有,但平台已经内置
# 导入数据分析库
import pandas as pd  # 数据表操作
import matplotlib.pyplot as plt  # 绘图
import seaborn as sns  # 高级统计绘图
from datetime import datetime  # 日期时间处理

数据读取与清洗

Listing 2: 读取并清洗电商数据
# 注:superstore.xlsx 数据文件本地没有,此处无法实际运行
# data = pd.read_excel('superstore.xlsx')  # 读取Excel销售数据
# del data['Postal Code']  # 删除邮政编码字段(缺失值多,分析贡献有限)
# print('数据形状:', data.shape)
# print(data.head())
  • 使用 pd.read_excel() 读取 Excel 格式销售数据
  • 删除缺失值较多的 Postal Code 字段
  • 通过 .shape.head() 初步了解数据规模与结构

问题1:每天是否采用统一折扣?

分析方法:按订单日期分组,统计每天折扣种类数量

Listing 3: 每日折扣唯一性分析
# 注:依赖 superstore.xlsx 数据,此处展示分析逻辑
# daily_discounts = data.groupby('Order Date').Discount.nunique()
# print(daily_discounts.head(10))
# print(f'平均每天折扣种类数: {daily_discounts.mean():.2f}')

分析要求:先计算 daily_discounts.gt(1) 的实际占比、涉及日期数和缺失情况,再说明同一天出现多种折扣的现象。订单数据由教学平台用于固定练习,公开教材的拓展案例使用课程数据下载入口提供的企业财务数据。

问题2:各品类折扣情况如何?

分析方法:按子品类和折扣力度分组,统计利润与天数

Listing 4: 各品类折扣情况分析
# 注:依赖 superstore.xlsx 数据,此处展示分析逻辑
# category_discount = data.groupby(['Sub-Category', 'Discount']).agg({
#     'Profit': 'sum',        # 计算该品类在该折扣下的总利润
#     'Order Date': 'nunique'  # 统计该折扣持续的天数
# })
# category_discount['Profit_per_day'] = (
#     category_discount['Profit'] / category_discount['Order Date']
# )
# print(category_discount.head(15))

待执行判据:只有各品类折扣分布、样本量和期间均由实际输出支持后,才能描述品类差异;当前只保留待检验假设。

问题3:折扣与利润的总体关系

核心思路:剔除品类数量和折扣时间的影响

  • 按折扣分组,汇总销量、销售额、利润等指标
  • 先聚合实际出现的 折扣×产品×订单日 单元格,再对折扣组的观测单元求均值
  • 过滤掉样本量过小的极端折扣

按折扣分组统计业务指标

Listing 5: 折扣与利润关系深度分析
# 注:依赖 superstore.xlsx 数据,此处展示分析逻辑
# profit_by_discount = data.groupby('Discount').agg({
#     'Quantity': 'sum',       # 总销量
#     'Sales': 'sum',          # 总销售额
#     'Profit': 'sum',         # 总利润
#     'Order Date': 'nunique', # 不重复日期数
#     'Product Name': 'nunique' # 不重复产品数
# })
# profit_by_discount.columns = [
#     'Quantity_sum', 'Sales_sum', 'Profit_sum',
#     'Dates_sum', 'Products_sum'
# ]

按实际观测的产品日单元计算平均指标

核心公式

\[ \large \text{观测产品日平均利润} = \frac{\sum_{c\in C_d}\text{Profit}_c}{|C_d|} \]

其中 \(C_d\) 是折扣 \(d\) 下实际出现的“产品×订单日”单元集合。不能用“产品去重数×日期去重数”补出未发生的笛卡尔网格;若研究完整暴露网格,必须另有在售/可售记录并明确零成交单元。

Listing 6: 计算标准化业务指标
展开标准化指标代码
# 注:依赖 superstore.xlsx 数据,此处展示实际观测单元逻辑
# observed_cells = data.groupby(['Discount','Product Name','Order Date'], as_index=False).agg(
#     Profit=('Profit','sum'), Sales=('Sales','sum'), Quantity=('Quantity','sum')
# )  # 先把同一折扣、产品、订单日的多行合并为一个实际观测单元
# profit_by_discount = observed_cells.groupby('Discount').agg(
#     Profit_p_p=('Profit','mean'), Sales_p_p=('Sales','mean'),
#     Quantity_p_p=('Quantity','mean'), Observed_cells=('Profit','size')
# )  # 仅在实际出现的产品日单元上计算均值
# assert observed_cells['Profit'].sum() == data['Profit'].sum()  # 核对利润守恒

过滤极端值与数据可视化

Listing 7: 折扣与业务指标关系可视化
展开过滤与可视化代码
# 注:依赖 superstore.xlsx 数据,此处展示分析逻辑
# profit_filtered = profit_by_discount.query('Products_sum > 19')
# sns.set(style='darkgrid')
# plt.figure(figsize=(10, 6))
# for metric, label in zip(
#     ['Profit_p_p', 'Sales_p_p', 'Quantity_p_p'],
#     ['平均利润', '平均销售额', '平均销售数量']
# ):
#     sns.lineplot(x='Discount', y=metric, label=label, data=profit_filtered)
# plt.legend()
# plt.xlabel('折扣')
# plt.ylabel('数值')
# plt.title('折扣与业务指标关系')
# plt.show()
  • 过滤条件应改为事先设定的实际观测产品日单元数,并同时报告保留/剔除数量
  • 不能用产品种类数替代单元格样本量;极端折扣只做含/不含敏感性,不直接删除

待检验假设:利润拐点

“折扣 20% 是利润正负拐点”仅是平台材料中的待检验假设;本仓库没有可访问订单快照,不发布事实结论。

折扣区间 利润情况 策略建议
< 20% 待运行检验 不预称安全区间
> 20% 待运行检验 不预称负利润区间

待校准假设:折扣策略

低折扣策略只是待检验候选

  • 0.2% 与 7% 只作为候选折扣点;须报告样本量、分母、误差与基线后再判断,不称“最优”或“显著提升”
  • 小幅折扣是否提高购买量必须通过同一时间段的基准方法或随机对照检验
  • 销量与利润可能方向相反,须同时报告增量毛利、成本与不确定性

关键发现:极端折扣的警示

85%、55%、57% 是否出现异常负利润必须由可访问数据核对;当前只列为待检验异常点。

  • 先核对是否属于录入错误、特定商品或引流活动
  • 同时报告包含与不包含极端点的敏感性结果
  • 不得为了获得整齐关系而直接过滤;剔除规则必须事先设定并保留检查记录

商业建议总结

策略方向 具体建议
常规定价 先按折扣组报告样本量、利润与不确定性,再审批阈值
促销策略 将 0.2%、7%、20% 作为候选敏感性点,不预称最优
亏损核对 先确认实际观测、成本和不确定性,再决定是否继续小范围试用
品类比较 先比较各品类样本量与折扣分布;依据不足时只作为待验证的假设

折扣试验的判断条件

  • 结果性质:教学平台的订单结果用于说明折扣分析方法;企业财务案例的结果来自课程下载数据,两者应分别解释。
  • 后续处理:只有在数据来源明确、比较方法一致且判断标准已经说明时,才考虑小范围试用。
  • 基线与指标:增量毛利、销量、退货/客诉、库存与触达成本;同时报告含/不含极端点结果。
  • 什么时候需要重新检查:字段或期间不完整、利润或客诉超出事先设定的范围,或结果不优于基准时,先暂停试用;下月第 5 个工作日再次查看结果。

运行前预测|平台任务解答代码

  • 输入预测:运行前先写出 datahuigui01huigui03profit_8discount 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。
  • 结果预测:不展开答案,先预测将得到ax 的结果;同时写出方向、数量级或表格/图形结构。
  • 完成要求:能独立说明本任务从输入到“平台任务解答代码”结果的关键步骤,原样录入平台代码并得到可核对的运行结果。

⭐ 平台任务解答代码

展开完整代码(投影默认折叠)
# 注:superstore.xlsx 数据文件本地没有,但平台已经内置
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
# 导入必要的包
import pandas as pd # 用于数据处理和分析
import matplotlib.pyplot as plt # 用于绘图
import seaborn as sns # 用于高级绘图
from datetime import datetime # 用于处理日期时间数据

# 读取Excel文件
data = pd.read_excel('superstore.xlsx')  

# 删除Postal Code字段
del data['Postal Code']  
print(data.head())  # 输出前几行数据

# 折扣与销售利润关系探究

# 判断每一天是不是同一个折扣
huigui01 = data.groupby('Order Date').Discount.nunique()  
print(huigui01.head())  # 输出前几行数据

# 判断每个品类的折扣情况
huigui03 = data.groupby(['Sub-Category', 'Discount']).agg({
  'Profit': 'sum', # 计算每个子类别和折扣组合的总利润
  'Order Date': 'nunique', # 计算每个子类别和折扣组合的唯一订单日期数量
})  # 数据结构定义结束
huigui03['Profit_pd'] = huigui03['Profit'] / huigui03['Order Date'] # 计算单位时间内的平均利润
print(huigui03.head(15)) # 打印前15行结果,检查每个子类别和折扣组合的利润情况

# 通过前面的判断,可以发现:
# 1)同一天不同商品会采取不同的折扣;
# 2)不同品类的商品,折扣力度也并不相同;
# 为了简化问题,我们将所有销售数据按照折扣分组,然后对销量、销售额、利润等数据进行汇总聚合;
# 同时,考虑到折扣促销的本质,就是为了通过降价提高销量,相应单个产品的利润会有所下降,但是单个品类、单位时间的利润总和会得到提升;
# 因此我们在探究折扣与利润之间关系时候,需要剔除品类数量、折扣时间的影响。

# 按折扣分组,计算汇总指标
profit_8discount = data.groupby('Discount').agg({
  'Quantity': 'sum', # 计算每个折扣下的总销售数量
  'Sales': 'sum', # 计算每个折扣下的总销售额
  'Profit': 'sum', # 计算每个折扣下的总利润
  'Order Date': 'nunique', # 计算每个折扣下的唯一订单日期数量
  'Product Name': 'nunique', # 计算每个折扣下的唯一商品名称数量
})  # 数据结构定义结束

# 重命名列
profit_8discount.columns = ['Quantity_sum', 'Sales_sum', 'Profit_sum', 'Dates_sum', 'Products_sum']

# 计算单位时间内每个商品的平均利润、平均销售额和平均销售数量
profit_8discount['Profit_p_p'] = profit_8discount['Profit_sum'] / profit_8discount['Products_sum'] / profit_8discount['Dates_sum'] # 平均利润
profit_8discount['Sales_p_p'] = profit_8discount['Sales_sum'] / profit_8discount['Products_sum'] / profit_8discount['Dates_sum'] # 平均销售额
profit_8discount['Quantity_p_p'] = profit_8discount['Quantity_sum'] / profit_8discount['Products_sum'] / profit_8discount['Dates_sum'] # 平均销售数量

# 重置索引,方便后续操作
profit_8discount = profit_8discount.reset_index()
print(profit_8discount)  # 输出利润数据

# 选取折扣涉及商品种类大于(商品种类总数)*0.005的情形;
profit_8discount22 = profit_8discount.query('Products_sum > 19') 
print(profit_8discount22)  # 输出利润数据

# 绘制折扣与利润关系的折线图
sns.set(style="darkgrid") # 设置绘图风格为'darkgrid'
plt.figure(figsize=(10, 6)) # 设置画布大小

# 遍历需要绘制的列(平均利润、平均销售额、平均销售数量)
for i in profit_8discount22.columns[6:-2]:
  ax = sns.lineplot(x='Discount', y=i, label=i, data=profit_8discount22)  # 绘制折线图

# 添加图例和标签
plt.legend() # 显示图例
plt.xlabel('Discount Range') # 设置x轴标签
plt.ylabel('Sales') # 设置y轴标签
plt.savefig("10.png") # 保存图表为PNG文件
plt.show() # 显示图表

# 通过分析发现:
# 以下三点为平台固定材料中的待检验叙述;运行后须报告样本量、分母与误差,不直接发布拐点、最优或因果结论。
# 候选敏感性点包括0.002、0.07、0.2、0.55、0.57与0.85;每一点均需与事先设定基线比较。
# 若样本或期间不足,说明需要检查的数据和缺少的内容。

任务复盘|平台任务解答代码

运行后核对:核对 datahuigui01huigui03profit_8discount 是否按预测参与运算,实际输出是否与预测一致;若不一致,先检查类型、单位、索引/字段和运算顺序。

拓展练习:只改变一个关键输入或业务场景,先预测输出如何变化,再运行验证并解释变化原因。

随堂练习

  • 问题 1|怎样完成本章分析?:运行折扣汇总与按产品和日期汇总,写出 Discount×Product Name×Order Date 单元数、单元均值、折扣组总额及利润守恒检查;不得使用“产品数×天数”作为稀疏订单分母。
  • 问题 2|结果说明什么?:依据教师区“中国本地解答”,写出从 revenue/sell_exp/net_profit 到销售费用率和净利率的计算步骤;如果分母为零、报告版本冲突或期间超出 2018—2025,应先检查原因。
  • 问题 3|换一个情境,怎样继续应用?:把同一财报分析方法从焦点科技拓展应用到浙江壹网壹创,保持字段、期间与双最低要求不变;写出拓展应用前后行数、最新两项比率、状态差异和期间检查。
  • 作答提示:请完成三道题,并在回答中引用实际运行结果;拓展练习中不要把课堂示例写成普遍规律或因果结论。
  • 学习说明:平台订单练习用于学习折扣分组方法;中国企业财务案例用于练习费用率、利润率和趋势比较。两部分回答的问题不同,应分别完成。

教师参考解答

教师参考解答|答案与说明 1

  • 所用数据与字段:平台折扣表字段 Order Date/Sub-Category/Discount/Profit/Quantity/Sales/Product Name;中国代理资产为 stock_basic_datafinancial_statement,字段 ts_code/name/area/end_date/revenue/sell_exp/net_profit,固定 2018—2025 年
  • 平台练习答案|折扣分组、标准化指标与核对(平台保护块之外):

教师参考解答|代码 1

展开代码(代码区可独立滚动)
import pandas as pd  # 导入表格库
def summarize_platform_discounts(superstore):  # 定义平台折扣分析接口
    required={'Order Date','Sub-Category','Discount','Profit','Quantity','Sales','Product Name'}  # 对齐平台任务字段
    if not required<=set(superstore.columns): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 缺列时停止
    clean=superstore.dropna(subset=list(required)).drop_duplicates().copy()  # 清除关键缺失与完全重复行
    if clean.empty: raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 空样本时停止
    clean['Order Date']=pd.to_datetime(clean['Order Date'])  # 统一订单日期
    cells=clean.groupby(['Discount','Product Name','Order Date'],as_index=False).agg(quantity=('Quantity','sum'),sales=('Sales','sum'),profit=('Profit','sum'))  # 合并实际出现的折扣产品日单元
    grouped=cells.groupby('Discount').agg(quantity=('quantity','sum'),sales=('sales','sum'),profit=('profit','sum'),observed_cells=('profit','size'),profit_per_product_day=('profit','mean'),sales_per_product_day=('sales','mean'),quantity_per_product_day=('quantity','mean'))  # 在实际观测单元上汇总总额与均值
    if grouped['observed_cells'].eq(0).any(): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 实际观测单元为零时停止
    assert grouped['profit'].sum()==clean['Profit'].sum()==cells['profit'].sum()  # 核对两层聚合利润守恒
    return grouped,{'raw_rows':len(superstore),'clean_rows':len(clean),'profit_total':clean['Profit'].sum()}  # 返回行数与利润核对结果

教师参考解答|答案与说明 2

  • 完整答案|对象、口径与指标计算(平台保护块之外):

教师参考解答|代码 2

展开代码(代码区可独立滚动)
def select_latest_disclosure(frame,value_fields):  # 统一财报披露版本选择约定
    required={'ts_code','end_date',*value_fields}; versions=[c for c in ['ann_date','f_ann_date'] if c in frame.columns]  # 固定键与可接受版本字段
    if not required<=set(frame.columns): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 缺列时停止
    work=frame.dropna(subset=list(required)).copy(); work['end_date']=pd.to_datetime(work['end_date'],errors='coerce')  # 清理必需字段
    for column in versions: work[column]=pd.to_datetime(work[column],errors='coerce')  # 解析披露日期
    keys=['ts_code','end_date']; work=work.dropna(subset=['end_date']); duplicate_mask=work.duplicated(keys,keep=False); before=int(duplicate_mask.sum())  # 统计选择前重复
    if before and (not versions or work.loc[duplicate_mask,versions].isna().all(axis=1).any()): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 无版本依据时停止
    work['_version']=work[versions].max(axis=1) if versions else pd.NaT  # 合并双版本字段为排序键
    latest_version=work.groupby(keys)['_version'].transform('max') if versions else pd.Series(pd.NaT,index=work.index)  # 为每个公司报告期定位最晚披露时点
    latest_rows=work.loc[~duplicate_mask | work['_version'].eq(latest_version)].copy()  # 仅保留单例或并列最晚版本
    tied_mask=latest_rows.duplicated(keys,keep=False); tied_latest_rows=int(tied_mask.sum())  # 统计并列最晚版本行
    conflicting_latest_keys=int(latest_rows.loc[tied_mask].groupby(keys,dropna=False)[value_fields].nunique(dropna=False).gt(1).any(axis=1).sum()) if tied_latest_rows else 0  # 统计并列且数值冲突的披露键
    if conflicting_latest_keys: raise ValueError(f'输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 并列最新值冲突时请先检查数据后再继续
    selected=latest_rows.drop_duplicates(keys+value_fields).drop_duplicates(keys).drop(columns='_version',errors='ignore')  # 仅合并数值完全一致的并列行
    after=int(selected.duplicated(keys).sum()); audit={'duplicate_rows_before':before,'tied_latest_rows':tied_latest_rows,'conflicting_latest_keys':conflicting_latest_keys,'duplicate_rows_after':after,'version_fields':versions}  # 返回并列与冲突检查
    if after: raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 选择后仍重复则停止
    return selected,audit  # 返回唯一版本与检查依据

教师参考解答|代码 3

展开代码(代码区可独立滚动)
from pathlib import Path  # 导入路径工具
import pandas as pd  # 导入表格库
import numpy as np  # 导入有限值检查工具
root=Path('/home/ubuntu/r2_data_mount/data/stock')  # 指定股票目录
basic_path,fs_path=root/'stock_basic_data.h5',root/'financial_statement.h5'  # 指定可用HDF资产
if not basic_path.exists() or not fs_path.exists(): raise FileNotFoundError('未找到课程数据文件,请从课程数据下载入口获取并核对文件位置')  # 缺失即停止
basic=pd.read_hdf(basic_path,key='stock_basic_info',columns=['order_book_id','symbol','province']).rename(columns={'order_book_id':'raw_code','symbol':'name','province':'area'})  # 只读取公司筛选字段并标准化
basic['ts_code']=basic['raw_code'].str.replace('.XSHG','.SH',regex=False).str.replace('.XSHE','.SZ',regex=False)  # 统一证券代码后缀
basic['area']=basic['area'].astype('string').str.replace(r'[省市]$','',regex=True)  # 统一省市简称
required_basic={'ts_code','name','area'}  # 定义公司对象字段
required_financial={'ts_code','end_date','revenue','sell_exp','net_profit'}  # 定义销售费用率与净利率字段
focus=basic.loc[basic['ts_code'].eq('002315.SZ'),['ts_code','name','area']]  # 锁定南京焦点科技
if len(focus)!=1: raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 对象不唯一时停止
focus_raw_code=basic.loc[basic['ts_code'].eq('002315.SZ'),'raw_code'].iloc[0]  # 取得HDF原始代码以高效筛选
fs=pd.read_hdf(fs_path,key='financial_data',where='order_book_id == focus_raw_code',columns=['order_book_id','quarter','info_date','operating_revenue','selling_expense','net_profit']).rename(columns={'order_book_id':'ts_code','quarter':'end_date','info_date':'ann_date','operating_revenue':'revenue','selling_expense':'sell_exp'})  # 按目标公司读取营收、销售费用与净利润
fs['ts_code']=fs['ts_code'].str.replace('.XSHG','.SH',regex=False).str.replace('.XSHE','.SZ',regex=False)  # 统一财报证券代码后缀
fs['end_date']=pd.PeriodIndex(fs['end_date'].str.upper(),freq='Q').end_time.normalize()  # 将季度键转换为报告期末日期
if not required_basic<=set(basic.columns) or not required_financial<=set(fs.columns): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 标准化后仍缺列即停止
fs,version_audit=select_latest_disclosure(fs,['revenue','sell_exp','net_profit'])  # 统一保留最晚披露版本
analysis=fs.merge(focus,on='ts_code',how='inner',validate='many_to_one').sort_values('end_date').copy()  # 连接财报与公司信息并固定时间顺序
analysis=analysis.loc[analysis['end_date'].between('2018-01-01','2025-12-31')].copy()  # 严格锁定2018—2025报告期

教师参考解答|代码 4

展开代码(代码区可独立滚动)
if analysis.empty or analysis['end_date'].nunique()<5: raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 空连接或期间不足时停止
if analysis['revenue'].eq(0).any() or not np.isfinite(analysis[['revenue','sell_exp','net_profit']].to_numpy()).all(): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 比率检查要求
analysis['selling_expense_rate']=analysis['sell_exp']/analysis['revenue']  # 计算销售费用率
analysis['net_profit_margin']=analysis['net_profit']/analysis['revenue']  # 计算净利率并与任务口径一致
if not np.isfinite(analysis[['selling_expense_rate','net_profit_margin']].to_numpy()).all(): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 非有限比率停止
analysis['fiscal_year']=analysis['end_date'].dt.year  # 构造财政年键
analysis['fiscal_quarter']=analysis['end_date'].dt.quarter  # 构造财政季度键
if analysis.duplicated(['fiscal_year','fiscal_quarter']).any(): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 披露选择后期间键仍不唯一时停止
prior_revenue=analysis[['fiscal_year','fiscal_quarter','revenue']].rename(columns={'revenue':'prior_year_revenue'}).copy()  # 建立上年同季收入查找表
prior_revenue['fiscal_year']=prior_revenue['fiscal_year']+1  # 将历史年键前移一年以匹配当期
analysis=analysis.merge(prior_revenue,on=['fiscal_year','fiscal_quarter'],how='left',validate='one_to_one')  # 按年与季度精确连接同比分母
analysis['revenue_yoy']=np.where(analysis['prior_year_revenue'].notna() & analysis['prior_year_revenue'].ne(0),analysis['revenue']/analysis['prior_year_revenue']-1,np.nan)  # 仅在上年同季分母可用时计算同比
print(version_audit,analysis[['ts_code','name','area','end_date','revenue','selling_expense_rate','net_profit_margin','revenue_yoy']])  # 输出数据版本检查与双指标表

教师参考解答|答案与说明 3

  • 完整答案|另行核对与阈值敏感性

教师参考解答|代码 5

展开代码(代码区可独立滚动)
ratio_check=analysis[['sell_exp','net_profit']].div(analysis['revenue'],axis=0)  # 独立重算销售费用率与净利率
assert ratio_check['sell_exp'].equals(analysis['selling_expense_rate'])  # 核对销售费用率
assert ratio_check['net_profit'].equals(analysis['net_profit_margin'])  # 核对净利率
sensitivity=pd.DataFrame({'selling_rate_ceiling':[.03,.05,.08],'net_margin_floor':[.05,.03,0]})  # 定义三组双最低要求课堂情景
sensitivity['latest_selling_rate']=analysis['selling_expense_rate'].iloc[-1]  # 固定最新报告期费用率
sensitivity['latest_net_margin']=analysis['net_profit_margin'].iloc[-1]  # 固定最新报告期净利率
sensitivity['status']=sensitivity.apply(lambda row:'REVIEW' if row['latest_selling_rate']>row['selling_rate_ceiling'] or row['latest_net_margin']<row['net_margin_floor'] else 'PASS',axis=1)  # 任一最低要求失败即核对
sensitivity['threshold_status']='课堂预算情景,待真实预算批准'  # 标明阈值尚非生产政策
sensitivity['owner']='跨境电商财务负责人'  # 指定核对责任角色
sensitivity['action']=sensitivity['status'].map({'REVIEW':'暂缓扩大使用并核对费用','PASS':'继续观察'})  # 记录建议
sensitivity['recheck_when']='输入字段改变或连续两期超预算'  # 定义升级需要重新检查的情况
sensitivity['recheck_date']='下一季度财报公布后第5个工作日'  # 事先设定再次检查时间
assert analysis['end_date'].between('2018-01-01','2025-12-31').all()  # 独立核验固定期间
print({'n':len(analysis),'start':analysis['end_date'].min(),'end':analysis['end_date'].max()},sensitivity)  # 输出期间与双最低要求

教师参考解答|答案与说明 4

  • 拓展应用答案|浙江壹网壹创同口径核对

教师参考解答|代码 6

展开代码(代码区可独立滚动)
alternative_raw_code='300792.XSHE'  # 事先设定同属互联网服务业的浙江壹网壹创
alternative_financials=pd.read_hdf(fs_path,key='financial_data',where='order_book_id == alternative_raw_code',columns=['order_book_id','quarter','info_date','operating_revenue','selling_expense','net_profit']).rename(columns={'order_book_id':'ts_code','quarter':'end_date','info_date':'ann_date','operating_revenue':'revenue','selling_expense':'sell_exp'})  # 按相同真实字段结构读取新案例公司财报
alternative_financials['ts_code']=alternative_financials['ts_code'].str.replace('.XSHE','.SZ',regex=False)  # 统一新案例公司证券代码后缀
alternative_financials['end_date']=pd.PeriodIndex(alternative_financials['end_date'].str.upper(),freq='Q').end_time.normalize()  # 将新案例公司季度键转为报告期末
alternative_financials,alternative_version_audit=select_latest_disclosure(alternative_financials,['revenue','sell_exp','net_profit'])  # 按同一规则选择最晚披露版本
alternative_analysis=alternative_financials.loc[alternative_financials['end_date'].between('2018-01-01','2025-12-31')].sort_values('end_date').copy()  # 严格锁定新案例公司2018—2025期间
if alternative_analysis.empty or alternative_analysis['revenue'].eq(0).any(): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 没有有效分母时停止
alternative_analysis['selling_expense_rate']=alternative_analysis['sell_exp']/alternative_analysis['revenue']  # 按相同口径计算新案例销售费用率
alternative_analysis['net_profit_margin']=alternative_analysis['net_profit']/alternative_analysis['revenue']  # 按相同口径计算新案例净利率
alternative_latest=alternative_analysis.iloc[-1]  # 取得新案例公司最新合规报告期
alternative_status='REVIEW' if alternative_latest['selling_expense_rate']>.05 or alternative_latest['net_profit_margin']<.03 else 'PASS'  # 使用同一基准双最低要求形成新案例状态
assert alternative_analysis['end_date'].between('2018-01-01','2025-12-31').all()  # 核验新案例样本仍在固定期间
print({'source_rows':len(analysis),'alternative_rows':len(alternative_analysis),'source_latest':analysis[['selling_expense_rate','net_profit_margin']].iloc[-1].to_dict(),'alternative_latest':alternative_latest[['selling_expense_rate','net_profit_margin']].to_dict(),'alternative_status':alternative_status},alternative_version_audit)  # 输出新案例前后结构、比率与数据版本检查

教师参考解答|答案与说明 5

  • 解释答案:先把实际出现的“折扣×产品×日期”作为一条观察记录,再按折扣汇总总额和平均值;汇总前后的利润总额应一致。不能用产品数乘日期数来补出并不存在的记录。中国企业案例比较营业收入、销售费用和净利润,但费用率变化不能证明某次促销造成了利润变化。
  • 拓展应用答案:上方代码把对象替换为浙江壹网壹创,保持真实字段、2018—2025与 .05/.03 基准最低要求;输出拓展应用前后行数、最新费用率/净利率和状态,并用期间检查及数据版本检查核对。
  • 参考结果:平台练习包括各折扣组的销量、销售额、利润、实际产品日数量和平均值;中国企业案例包括报告期、样本量、费用率、净利率及不同预算要求下的处理建议。所需财务数据可从课程数据下载入口取得。
  • 边界 / 局限:公司财务比率不等同平台订单因果
  • 常见错误:漏掉 sell_exp 却声称计算费用率;用名称连接;累计和单季口径混用